#include "nPatriciaTrie.h"
#include "linkedlist.h"
#include "stopwatch.h"
#include "addremove.h"
#include "tagdefs.h"
#include "sharedseg.h"
#include "fileperm.h"
#include "client.h"
#include <stdio.h>
#include <string.h>
#include <QDateTime>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <string.h>
#define DONOTCHECKFILEPERMISSION
char *commonheadkey;

char alphabets[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
linkedlist *hierlist;
nPatriciaTrie<char> *engwords;
nPatriciaTrie<char> *tstfiles;
char WORDGOT[300];
long avg1,avg2;
long first1,first2;
long count1,count2;
long countoperations;
long testfilescount;
long engwordcount;
#define NOIPCNOTIFICATION
void randomize() {
	time_t t;
	srand((unsigned int)time(&t));
}
void freeup()  {
    printf("Unloading english wordlist\n");
engwords->recursive_remove(engwords->head);
    printf("unloading Test Files trie\n");
tstfiles->recursive_remove(tstfiles->head);
}
void genword(int maxlen) {
	// Generate a word of maximum length maxlen
	int i,len,j;
	int alphalen;
	char st[50];
	len = (int)rand()%maxlen;
                if (len<5)	
		len = 5;   // min length 5
	alphalen=strlen(alphabets);
	for(i=0;i<len;i++) {
		j=(int)(rand()%alphalen);
		st[i]=alphabets[j];
	}
	st[i]='\0';
	strcpy(WORDGOT,st);
}
void initializetest() {
    loadenglishlist();
    printf("English word list loaded successfully\n");
}
void loadenglishlist() {
                engwords = new nPatriciaTrie<char>;
	engwordcount=0;
	FILE *fp;
	char st[100];
	fp=fopen("wordlist.txt","r");
	if (fp==NULL) {
	    printf("Cannot load wordlist file\n");
	    return;
	}
	do {
		fscanf(fp,"%s",st);
		engwords->Insert(st,'\0');
		engwordcount++;
	}while(!feof(fp));
	fclose(fp);
}
void englishword() {
    long which;
    which = (rand()%engwordcount);
    linkedlist *tmp;
    tmp=engwords->GetKey(which);
    strcpy(WORDGOT,tmp->remove());
    //printf("%s\n",WORDGOT);
}
void maketestfilestrie() {
                tstfiles = new nPatriciaTrie<char>;
  	linkedlist *files;
	testfilescount=0;
	files=clientlistfiles((char*)FLATPREFIX);
	while(!files->isEmpty())  {
	    tstfiles->Insert(files->remove(),'\0');
	    testfilescount++;
	}
}
linkedlist *getsometestfiles() {
  /*  
                linkedlist *list,*files,*tmplist;
	int howmany,r;
	char *data;
	files=clientlistfiles(FLATPREFIX);
	howmany=rand()%(files->count())+1;
	howmany=(howmany%20)+1;
	list=new linkedlist();
	while (howmany>0) {
		howmany--;
		tmplist=files->copyList();
		r=rand()%(tmplist->count());
		while (r>0) {
			r--;
			tmplist->remove();
		}
		if (!tmplist->isEmpty()) {
			data=strdup(tmplist->remove());
			files->removekey(data);
			list->add(data);
		}
	}
	return list;
*/	
                linkedlist *list;
	int howmany,which;
	char *data;
	howmany=(rand()%20)+1;
	list=new linkedlist();
	while (howmany>0) {
	    which=(rand()%testfilescount)+1;
	    data=strdup((tstfiles->GetKey(which))->remove());
	    //printf("%d ::: %d (%d) : %s\n",howmany,which,testfilescount,data);
	    list->add(data);
	    free(data);
	    howmany--;
	}
	return list;
}
void  addrandomflattags(char *filename) {
                QTime timetaken;
	long elapse;
	int howmany;
	howmany = (int) (rand()%4)+1;
//	char tag[300];
	linkedlist *list=new linkedlist();
	//printf("%s ::: %d tags\n",filename,howmany);
	for (int i=0;i<howmany;i++) {
		englishword();
		list->add(WORDGOT);
	}
	list->add((char*)FLATPREFIX);
	//printf("HERE2222^^^^^^^^\n");
	timetaken = QTime(0,0);
	timetaken.restart();
	//$$$$
	//printf("ADD %s : %s\n",filename,list->toString());
	clientaddtags(filename,list);
	elapse=timetaken.elapsed();
	countoperations++;
	if (countoperations==1) 
	    first1=elapse;
	avg1=((avg1*(countoperations-1)+elapse)/countoperations);
    	//printf("%s : add tags %s (Time : %d (%ld) msecs) ---- %ld\n",filename,list->toString(),(int)elapse,avg1,countoperations);
}
void  recursehier(int level,char prefix[300]) {
	if (level<=0)
		return;
	char tag[300];
	int howmany,i;
	howmany = (int) (rand()%2)+1;
	//printf("%s :::: %d :::: %d \n",prefix,howmany,level);
	for (i=0;i<howmany;i++) {
		strcpy(tag,prefix);
		strcat(tag,"/");
		//printf("recurse hier  before englishword\n");
		englishword();
		//printf("recurse hier  after englishword\n");
		strcat(tag,WORDGOT);
		//printf("@@@@ %s\n",tag);
		hierlist->add(tag);
		recursehier(level-1,tag);
	}
}
void  addrandomhiertags() {
                QTime timetaken;
	long elapse;
	char filename[300];
	linkedlist *list;
	linkedlist *files,*tmplist;
	hierlist=new linkedlist();
	int howmany;
	howmany = (int) (rand()%3)+1;
	if (hierlist!=NULL)
	    hierlist->removeAll();
	else
	    hierlist = new linkedlist();
	//printf("HERE1111********\n");
	recursehier(howmany,(char*)HIERPREFIX);
	//printf("$$$$ HIERFILES : %s\n",hierlist->toString());
	list=hierlist->copyList();
	while  (!(list->isEmpty()))  {
	                tmplist=new linkedlist();
		tmplist->add(list->remove());
		files=getsometestfiles();
		while (!files->isEmpty()) {
	                                  timetaken = QTime(0,0);
	                                  timetaken.restart();
     			  strcpy(filename,files->remove());
			  //$$$$###
			  //printf("ADD %s : %s\n",filename,tmplist->toString());
			  clientaddtags(filename,tmplist);
			  elapse=timetaken.elapsed();
			  countoperations++;
			  if (countoperations==1) 
			      first1=elapse;
			  avg1=((avg1*(countoperations-1)+elapse)/countoperations);
			  
//			  printf("%s : add tags %s (Time : %d (%ld) msecs) ---- %ld --listcount %d\n",filename,tmplist->toString(),(int)elapse,avg1,countoperations,list->count());
		}
		delete files;
		delete tmplist;
	    }
}
void  addrandomtags() {
	linkedlist *file;
	char *filename;
	int i;
	file=clientlistfiles((char*)FLATPREFIX);
	i=rand()%(file->count());
	//printf("Random File : %d (%d)::",i,file->count());
	while (i>0) {
		i--;
		file->remove();
	}
	filename=strdup(file->remove());
	//printf(" %s\n",filename);
	addrandomflattags(filename);
	free (filename);
}
void  removerandomflattags(char *filename) {
                QTime timetaken;
	long elapse;
	linkedlist *list,*removelst;
	char *tag;
	int i,j;
	list=clientlisttags(filename);
	i=rand()%(list->count());
	removelst=new linkedlist();
	while (i>0) {
		i--;
		list=clientlisttags(filename);
		list->removekey((char*)FLATPREFIX);
		list->sort();
		removelst->sort();
		list->sortedselfminus(removelst);
		j=rand()%(list->count());
		while (j>0) {
			j--;
			list->remove();
		}
		tag=strdup(list->remove());
		removelst->add(tag);
		delete list;
	}
	if (removelst->isEmpty())
		return;
	timetaken = QTime(0,0);
	timetaken.restart();
     	//$$$$
	//printf("REMOVE %s : %s\n",filename,removelst->toString());
	clientremovetags(filename,removelst);
	elapse=timetaken.elapsed();
		countoperations++;
		if (countoperations==1) 
		    first1=elapse;
		avg1=((avg1*(countoperations-1)+elapse)/countoperations);
	//printf("%s : remove tags %s (Time : %d (%ld) msecs)  ---- %ld\n",filename,removelst->toString(),(int)elapse,avg1,countoperations);
//		delete removelst;
}
void  removerandomtags() {
	linkedlist *file;
	char *filename;
	file=getsometestfiles();
	filename=strdup(file->remove());
	removerandomflattags(filename);
//	delete file;
	free(filename);
}

void  addtestfiles(long N) {
	char *filename;
	char command[300];
	sprintf(command,"mkdir /home/nandakiran/test/testscript >/dev/null");
	system(command);
	for (long i=0;i<N;i++) {
	    printf("TestFile : %ld\n",i+1);
	   englishword();
	filename=strdup(WORDGOT);
	if (filename==NULL) {
	    printf("Cannot allocate memory!\n");
	    return;
	}
	sprintf(command,"cp /home/nandakiran/data /home/nandakiran/test/testscript/%s >/dev/null",filename);
	//$$$$
	printf("%s \n",command);
	system(command);
	sprintf(command,"/home/nandakiran/test/testscript/%s",filename);
	addrandomflattags(command);
    }
  }
linkedlist* timedclientsearch(char *which,linkedlist* tags) {
               QTime timetaken;
	long howmany,elapse;
	
	howmany=0;
	avg1=0;
	
                inithandshake();
	// Get files 

	// Wait for Semaphore
	#ifndef NOIPCNOTIFICATION
	printf("Waiting for semaphore(Server to become free)!!!\n");
	#endif
       
       	sem_wait(client_sem);

	// Got Semaphore 
	#ifndef NOIPCNOTIFICATION
	printf("Server is free, sending data!!!\n");
	#endif
       	
       	strcpy(segptr->command,which);
       	strcpy(segptr->param1,tags->toString());
		
	#ifndef NOIPCNOTIFICATION
	printf("Sending command %s!!!\n",which);
	#endif
	
	// Begin Timer       	
	timetaken = QTime(0,0);
	timetaken.restart();
	// Release Semaphore
	sem_signal(server_sem);
	sem_wait(client_sem);
	
	linkedlist* result=new linkedlist();
	int i;	
	if (strcmp(segptr->result,"OVER")!=0) {
		// We have some data
		do {
			for (i=0;i<DTP;i++) {
				if (strlen(segptr->data[i])!=0) {
					result->add(segptr->data[i]);
					//printf("%s ",segptr->data[i]);
				} else
					break;
			}
		                // End Timer and restart timer
		               elapse=timetaken.elapsed();
			if (howmany >0 )  {
			    avg1=(avg1*howmany);
			    avg1+=elapse;
			    avg1/=(howmany+1);
			} else {
			    avg1=elapse;
			    first1=elapse;
			}
			howmany++;
			printf("%ld \t\t %ld \t\t %ld\n",howmany,elapse,avg1);
			timetaken = QTime(0,0);
			timetaken.restart();
			
			
			// Handle to server and wait
			// Release Semaphore 
			sem_signal(server_sem);
			sem_wait(client_sem);	
		} while ((segptr->moredata)&&(strcmp(segptr->result,"OVER")!=0));		}
	// End timer
	elapse=timetaken.elapsed();
	if (howmany >0 )  {
	    avg1=(avg1*howmany);
	    avg1+=elapse;
	    avg1/=(howmany+1);
	} else {
	  avg1=elapse;
	   first1=elapse;
	}
	howmany++;
	count1=howmany;
	//isitreq
	closehandshake();
	timetaken = QTime(0,0);
	timetaken.restart();
	linkedlist *tmp=new linkedlist();
	while ((result!=NULL) && (!result->isEmpty())) {
			char str[300];
			strcpy(str,result->remove());
#ifndef DONOTCHECKFILEPERMISSION
			if (SOMEACCESS(str))
#endif				
				tmp->add(str);
	}
	printf("Post Process the results  . Time Taken : %d \n\n",timetaken.elapsed());		//delete result;
	return tmp;
	//return result;
}

linkedlist* timedclientgetsuggestions() {
                QTime timetaken;
	long howmany,elapse;
	
	howmany=0;
	avg2=0;
	first2=0;
	
                linkedlist* result=new linkedlist();
	int i;	
	inithandshake();
	// Get Suggestions

	// Wait for Semaphore
	#ifndef NOIPCNOTIFICATION
	printf("Waiting for semaphore(Server to become free)!!!\n");
	#endif
       
       	sem_wait(client_sem);

	// Got Semaphore 
	#ifndef NOIPCNOTIFICATION
	printf("Server is free, sending data!!!\n");
	#endif
       	
       	strcpy(segptr->command,"getsuggestions");
		
	#ifndef NOIPCNOTIFICATION
	printf("Sending command getsuggestions!!!\n");
	#endif
	
	// Begin Timer       	
	timetaken = QTime(0,0);
	timetaken.restart();
       	
	// Release Semaphore
	sem_signal(server_sem);
	sem_wait(client_sem);
	
	if (strcmp(segptr->result,"OVER")!=0) {
		// We have some data
		do {
			for (i=0;i<DTP;i++) {
				if (strlen(segptr->data[i])!=0) {
					result->add(segptr->data[i]);
				} else
					break;
			}
		                // End Timer and restart timer
		               elapse=timetaken.elapsed();
			if (howmany >0 )  {
			    avg2=(avg2*howmany);
			    avg2+=elapse;
			    avg2/=(howmany+1);
			} else {
			    avg2=elapse;
			    first2=elapse;
			}howmany++;
			timetaken = QTime(0,0);
			timetaken.restart();
			
			// Handle to server and wait
			// Release Semaphore
			sem_signal(server_sem);
			sem_wait(client_sem);	
		} while ((segptr->moredata)&&(strcmp(segptr->result,"OVER")!=0));
	}
               elapse=timetaken.elapsed();
	if (howmany >0 )  {
	    avg2=(avg2*howmany);
	    avg2+=elapse;
	    avg2/=(howmany+1);
	} else {
	    avg2=elapse;
	    first2=elapse;
	}
	howmany++;
                count2=howmany;	
	closehandshake();
	return result;
}

linkedlist* clientlistNfiles(linkedlist *tag)
{
    QTime timetaken;
	long howmany,elapse;
	char st[10];
	strcpy(st,"FIRST");
	howmany=0;
	avg1=0;
	bool more;
	inithandshake();
	linkedlist* result=new linkedlist();
	linkedlist* partresult=new linkedlist();
	// Wait for Semaphore
    #ifndef NOIPCNOTIFICATION
	printf("Waiting for semaphore(Server to become free)!!!\n");
	#endif
       
	sem_wait(client_sem);
	
	// Got Semaphore 
	#ifndef NOIPCNOTIFICATION
	printf("Server is free, sending data!!!\n");
 	#endif
	
	do {	
      	
       	strcpy(segptr->command,"listNfiles");
       	strcpy(segptr->param1,tag->toString());
       	strcpy(segptr->param2,st);
		#ifndef NOIPCNOTIFICATION
       	printf("Sending command listNfiles!!!\n");
	  	#endif
	   
       	// Begin Timer       	
       	timetaken = QTime(0,0);
       	timetaken.restart();
       	
       	// Release Semaphore
       	sem_signal(server_sem);
       	sem_wait(client_sem);
	
       	int i;	
       	partresult->removeAll();


       	while (strcmp(segptr->result,"OVER")!=0) {
	   
        for (i=0;i<DTP;i++) {
			if (strlen(segptr->data[i])!=0) {
				partresult->add(segptr->data[i]);
#ifndef DONOTCHECKFILEPERMISSION
                if (SOMEACCESS(segptr->data[i]))
#endif				
			                       result->add(segptr->data[i]);
				
			} else
				break;
		}
	                // End Timer and restart timer
		if (howmany%2==0) {
       		  elapse=timetaken.elapsed();
		   timetaken = QTime(0,0);
		   timetaken.restart();
	                  if (howmany >0 )  {
		     avg1=(avg1*(howmany/2));
		     avg1+=elapse;
		     avg1/=((howmany/2)+1);
		  } else {
		     avg1=elapse;
		     first1=elapse;
		 }
		}
		howmany++;

		// Handle to server and wait
		// Release Semaphore
		sem_signal(server_sem);
		sem_wait(client_sem);	
		strcpy(st,"REST");
                  }
		if (partresult->count()>0) 
		    more=true;
		else
		    more=false;
	strcpy(segptr->result,"NONE");
                } while(more);
	closehandshake();
	count1=howmany/2;
	//delete partresult;
	return result;
    }

